# -*- coding: utf-8 -*-
#   Copyright 2009, 2010 Thomas Olsen <tanghus@gmail.com>
#
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU Library General Public License as
#   published by the Free Software Foundation; either version 2 or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#
#   GNU General Public License for more details
#
#
#   You should have received a copy of the GNU Library General Public
#   License along with this program; if not, write to the
#   Free Software Foundation, Inc.,
#
#   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#
#

from urllib import urlencode
from PyQt4.QtCore import  Qt, QObject, QVariant, QString, QSize, SIGNAL
from PyQt4.QtGui import *
from PyKDE4.kdecore import *
from PyKDE4.kdeui import *
from PyKDE4.kio import *
from PyKDE4.plasma import Plasma
import os, simplejson
from mylogging import debug

translate_url='http://ajax.googleapis.com/ajax/services/language/translate?'
detect_url='http://ajax.googleapis.com/ajax/services/language/detect?'

class GoogleTranslator(QGraphicsWidget):
  def __init__(self,parent):
    QGraphicsWidget.__init__(self)
    self.applet = parent        
    
  def init(self):
    print ("GoogleTranslator: init")
    self.job_part_idx = 0
    self.job_part = ""
    self.jobs = {}
    self.swapping = False
    self.def_from = self.applet.cfg.readEntry("default_from", QString("en")).toString()
    #print self.def_from
    self.def_to = self.applet.cfg.readEntry("default_to", QString("de")).toString()
    #print self.def_to
    self.def_text = self.applet.cfg.readEntry("default_string", QString("Example text")).toString()

    invert = u"%scontents/icons/invert.png" % self.applet.package().path()
  
    self.invert_button = Plasma.ToolButton(self)
    self.invert_button.nativeWidget().setMaximumSize(QSize(24, 24))
    self.invert_button.nativeWidget().setIcon(KIcon(invert))
    self.invert_button.nativeWidget().setToolTip(i18n("Swap languages"))
    self.invert_button.clicked.connect(self.invert_languages)

    # Add detection of language.
    self.detect_button = Plasma.ToolButton(self)
    self.detect_button.nativeWidget().setMaximumSize(QSize(24, 24))
    self.detect_button.nativeWidget().setIcon(KIcon("system-search"))
    self.detect_button.nativeWidget().setToolTip(i18n("Detect language"))
    self.detect_button.clicked.connect(self.detect_language)

    title_label = Plasma.Label(self)
    title_label.nativeWidget().setWordWrap(False)
    title_label.setText(i18n("Google Translator"))
    title_label.setAlignment(Qt.AlignCenter)
    f = title_label.nativeWidget().font()
    f.setBold(True)
    title_label.nativeWidget().setFont(f)

    self.from_label = Plasma.Label(self)
    self.from_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)
    self.from_label.setText(i18n("From:"))
    self.from_label.nativeWidget().setAlignment(Qt.AlignRight)

    self.language_from = Plasma.ComboBox(self)
    #self.language_from.setToolTip(i18n("Select the language to translate from."))
    self.language_from.setZValue(2)

    self.to_label = Plasma.Label(self)
    self.to_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)
    self.to_label.setText(i18n("To:"))
    self.to_label.nativeWidget().setAlignment(Qt.AlignRight)

    self.language_to = Plasma.ComboBox(self)
    self.language_to.setZValue(1)

    self.text_label = Plasma.Label(self)
    self.text_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)
    self.text_label.setText(i18n("Text:"))
    self.text_label.nativeWidget().setAlignment(Qt.AlignRight)

    self.text = Plasma.LineEdit(self)
    self.text.setClearButtonShown(True)
    self.text.nativeWidget().setMaxLength(1000)
    #print unicode(self.def_text)
    self.text.setText(self.def_text)

    self.text.editingFinished.connect(self.text_editing_finished)

    self.go_button = Plasma.PushButton(self)
    self.go_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)
    self.go_button.setText(i18n("Go!"))
    self.go_button.clicked.connect(self.do_translate)

    self.translation_result = Plasma.LineEdit(self)
    self.translation_result.nativeWidget().setReadOnly(True)

    self.credits_label = Plasma.Label(self)
    self.credits_label.nativeWidget().setOpenExternalLinks(True)
    self.credits_label.setAlignment(Qt.AlignRight)
    logo = u"%scontents/images/google-attribution.png" % self.applet.package().path()
    self.credits_label.setText(i18n("<a href=\"http://translate.google.com/\"><img src=\"%s\"></a>" % logo))
    self.credits_label.setMinimumSize(170, 20)

    languages = self.get_languages()
    language_names = languages.keys()
    language_names.sort()
    i = from_idx = to_idx = 0
    for language_name in language_names:
      language_code = languages[language_name]
      #print str(language) + " - " + KGlobal.locale().languageCodeToName(language).toUtf8()
      if language_code == self.def_from:
	  from_idx = i
      if language_code == self.def_to:
	  to_idx = i
      self.language_from.nativeWidget().addItem(language_name, QVariant(language_code))
      self.language_to.nativeWidget().addItem(language_name, QVariant(language_code))
      i+=1

    self.language_from.nativeWidget().setCurrentIndex(from_idx)
    self.language_to.nativeWidget().setCurrentIndex(to_idx)
    if self.applet.nwmon.connected():
      self.do_translate(None)

    self.language_from.textChanged.connect(self.do_translate)
    self.language_to.textChanged.connect(self.do_translate)

    # Layout
    self.grid_layout = QGraphicsGridLayout(self)
    #self.grid_layout.setColumnStretchFactor(1, 6)
    header_layout = QGraphicsLinearLayout()
    header_layout.addItem(self.invert_button)
    header_layout.addItem(self.detect_button)
    header_layout.addItem(title_label)
    self.grid_layout.addItem(header_layout, 0, 0, 1, 2)
    #self.grid_layout.addItem(self.invert_button, 0, 0)
    #self.grid_layout.addItem(title_label, 0, 1)
    self.grid_layout.addItem(self.from_label, 1, 0)
    self.grid_layout.addItem(self.language_from, 1, 1)
    self.grid_layout.addItem(self.to_label, 2, 0)
    self.grid_layout.addItem(self.language_to, 2, 1)
    self.grid_layout.addItem(self.text_label, 3, 0)
    self.grid_layout.addItem(self.text, 3, 1)
    self.grid_layout.addItem(self.go_button, 4, 0)
    self.grid_layout.addItem(self.translation_result, 4, 1)
    self.grid_layout.addItem(self.credits_label, 5, 0, 1, 2)

    #self.applet.setLayout(self.grid_layout)
    self.setLayout(self.grid_layout)

    self.setMinimumSize(self.grid_layout.sizeHint(Qt.MinimumSize))

    print ("GoogleTranslator: init. Done")

  def setEnabled(self, state):
    debug("setEnabled(%i)" % state)
    self.invert_button.setEnabled(state)
    self.go_button.setEnabled(state)
    self.language_from.setEnabled(state)
    self.language_to.setEnabled(state)
    self.translation_result.setEnabled(state)
    self.text.setEnabled(state)

  def get_languages(self):
    languages = {}

    for language_code in KGlobal.locale().allLanguagesList():
      languages[KGlobal.locale().languageCodeToName(language_code)] = language_code

    return languages

  def invert_languages(self):
    #In-place value swapping
    #>>> a = 10
    #>>> b = 5
    #>>> a, b
    #(10, 5)

    #>>> a, b = b, a
    #>>> a, b
    #(5, 10)
    
    self.swapping = True
    idx_from = self.language_from.nativeWidget().currentIndex()
    self.language_from.nativeWidget().setCurrentIndex(self.language_to.nativeWidget().currentIndex())
    self.language_to.nativeWidget().setCurrentIndex(idx_from)
    self.swapping = False
    self.do_translate()
    
  def detect_language(self):
    if self.swapping or not self.applet.nwmon.connected():
      return
    params=urlencode( (('v',1.0),
		      ('ie', 'UTF8'),
                      ('q',self.text.text().toUtf8()))
                      )
    url=detect_url+params
    #print url
    self.applet.setBusy(True)
    #self.detect_button.setEnabled(False)
    job = KIO.get(KUrl(url), KIO.NoReload, KIO.HideProgressInfo)
    self.jobs[job] = {}
    self.jobs[job]['idx'] = 0
    self.jobs[job]['data'] = ""
    #self.jobs[job]['mimetype'] = ""
    job.data.connect(self.job_received)
    #job.mimetype.connect(self.job_mimetype)
    try:
      # This should work from KDE SC 4.5
      job.result.connect(self.detect_job_done)
    except AttributeError as (errno, strerror):
      print "I/O error({0}): {1}".format(errno, strerror)
      debug("missing new-style support for KIO.Job.result")
      QObject.connect(job, SIGNAL("result( KJob *)"), self.detect_job_done)

  def do_translate(self, language=None):
    if self.swapping or not self.applet.nwmon.connected():
      return
    #print "len jobs: %i" % len(self.jobs)
    # the 'language' argument is not used but has to be here!
    self.def_from = translate_from = str(self.language_from.nativeWidget().itemData(self.language_from.nativeWidget().currentIndex()).toString())
    self.def_to = translate_to = str(self.language_to.nativeWidget().itemData(self.language_to.nativeWidget().currentIndex()).toString())
    #self.def_to = translate_to = str(self.language_to.text())
    #self.def_from = translate_from = str(self.language_from.text())
    self.applet.cfg.writeEntry("default_from", translate_from)
    self.applet.cfg.writeEntry("default_to", translate_to)
    self.applet.cfg.writeEntry("default_string", self.text.text())
    self.applet.cfg.sync()
    #print "translate from: " + translate_from + " to: " + translate_to
    langpair='%s|%s' % (translate_from,translate_to)
    params=urlencode( (('v',1.0),
                      ('ie', 'UTF8'),
                      ('q',self.text.text().toUtf8()),
                      ('langpair',langpair),) )
    url=translate_url+params
    #print url
    self.applet.setBusy(True)
    self.invert_button.setEnabled(False)
    job = KIO.get(KUrl(url), KIO.NoReload, KIO.HideProgressInfo)
    self.jobs[job] = {}
    self.jobs[job]['idx'] = 0
    self.jobs[job]['data'] = ""
    #self.jobs[job]['mimetype'] = ""
    job.data.connect(self.job_received)
    #job.mimetype.connect(self.job_mimetype)
    try:
      job.result.connect(self.translation_job_done)
    except:
      debug("missing new-style support for KIO.Job.result")
      QObject.connect(job, SIGNAL("result( KJob *)"), self.translation_job_done)
    #job.result.connect(self.job_done)
    # Why is KTransferJob.result() signal not implemented in new style syntax?
    #job.infoMessage.connect(self.job_info)

  #def job_mimetype(self, job, mimetype):
  #  if self.jobs.has_key(job) and mimetype:
  #    print u"job_mimetype: %s" % mimetype
  #    self.jobs[job]['mimetype'] = mimetype

  def job_received(self, job, data):
    # This method is used for both do_detect and do_translate
    if self.jobs.has_key(job) and data: #len(data) > 0:
      #print "job_received\n"
      self.jobs[job]['data'] += str(data)

  def translation_job_done(self, job):
    debug("job_done")
    if self.jobs.has_key(job):
      d = unicode(self.jobs[job]['data'], encoding='utf-8')
      jsdata = simplejson.loads(d)
      if jsdata['responseStatus'] == 200:
        #print unicode(jsdata['responseData']['translatedText'])
        self.translation_result.setText(jsdata['responseData']['translatedText'])
      elif jsdata['responseStatus'] == 400:
        if jsdata['responseDetails'] != None:
	  self.applet.showMessage(KIcon("info"), i18n("Translation error: %s" % jsdata['responseDetails']), Plasma.ButtonOk)
          self.translation_result.setText(jsdata['responseDetails'])
        else:
	  self.applet.showMessage(KIcon("info"), i18n("Unknown translation error!"), Plasma.ButtonOk)
          self.translation_result.setText(i18n("Unknown translation error!"))
      else:
	self.applet.showMessage(KIcon("info"), i18n("Unknown translation error!"), Plasma.ButtonOk)
        self.translation_result.setText(i18n("Unknown translation error!"))
      del self.jobs[job]
      self.applet.setBusy(False)
      self.invert_button.setEnabled(True)

  def detect_job_done(self, job):
    debug("detect_job_done")
    if self.jobs.has_key(job):
      d = unicode(self.jobs[job]['data'], encoding='utf-8')
      #d = QString.fromUtf8(self.jobs[job]['data'])
      #print d
      jsdata = simplejson.loads(d)
      print jsdata
      lang = ""
      if jsdata['responseStatus'] == 200:
        debug(jsdata['responseData']['language'])
        lang = jsdata['responseData']['language']
      elif jsdata['responseStatus'] == 400:
        if jsdata['responseDetails'] != None:
	  self.applet.showMessage(KIcon("info"), i18n("Language detection error: %s" % jsdata['responseDetails']), Plasma.ButtonOk)
          self.translation_result.setText(jsdata['responseDetails'])
        else:
	  self.applet.showMessage(KIcon("info"), i18n("Unknown translation error!"), Plasma.ButtonOk)
          self.translation_result.setText(i18n("Unknown detection error!"))
      else:
        #self.applet.showMessage(QIcon("info"), i18n("Unknown translation error!"), Plasma.MessageButton.ButtonOk(0))
	self.applet.showMessage(KIcon("info"), i18n("Unknown translation error!"), Plasma.ButtonOk)
        self.translation_result.setText(i18n("Unknown detection error!"))
      #self.job_part = "" # to be removed
      del self.jobs[job]
      self.applet.setBusy(False)
      #self.detect_button.setEnabled(True)

      languages = self.get_languages()
      language_names = languages.keys()
      language_names.sort()
      i = 0
      for language_name in language_names:
        language_code = languages[language_name]
        if str(language_code).upper() == lang.upper():
          self.language_from.nativeWidget().setCurrentIndex(i)
          break
        i+=1
      else:
        debug(u"Detected language %s was not found in KDE." % lang)


  def job_info(self, job, info):
    debug("job_info %s: " % str(info))

  def text_editing_finished(self):
    if len(self.text.text()) > 0:
      self.applet.cfg.writeEntry("default_text", self.text.text())
      self.applet.cfg.sync()
      self.do_translate()

